import bpy
from bpy.types import Operator
from itertools import chain

import mathutils
import math


import engine.initLIB.load_dll as engineLib
import ctypes


from 全局控制.Node.节点和插座基类.bl_UpdateNode import *
from 对象操作 import bl_对象变换帧

import 全局控制.Node.节点和插座基类.bl_节点基类 as 基类

import pdb





engineLib.flexCAPI.f_创建置物体变换节点.restype = ctypes.c_bool
engineLib.flexCAPI.f_创建_物体变换插帧_节点.restype = ctypes.c_bool





def f_create_3F_插座(self, names):
	for name in names:
		self.inputs.new('C_NodeSocket_f', name=name)


E_类型枚举_变换 = [
	("TYPE_变换单例", "单例", "", 0),

	("TYPE_位置", "location", "", 1),
	("TYPE_旋转", "rotation_euler", "", 2),
	("TYPE_缩放", "scale", "", 3),
	
]








def f_update_物体坐标系转换(self, context):
	if context:
		self.id_data.f_节点数据更新_更新树([self])


class C_get物体变换属性(基类.C_Node_基类):
	bl_dname = 'bl_node_get物体属性变换'
	bl_label = '取物体属性变换'
	
	m_坐标系转换 = bpy.props.EnumProperty(items=基类.E_类型枚举_坐标系轴向, default='TYPE_右手转左手', name="坐标系转换", update=f_update_物体坐标系转换)
	def init(self, context):
		super(C_get物体变换属性, self).f_init(context)
		self.inputs.new('C_Socket_物体_Array1D', name='物体')

		self.outputs.new('C_Socket_Vec3_Array1D', name='移动')
		self.outputs.new('C_Socket_Vec3_Array1D', name='旋转')
		self.outputs.new('C_Socket_Vec3_Array1D', name='缩放')
		self.outputs.new('C_Socket_Vec4_Array1D', name='方向')
		self.outputs.new('C_Socket_矩阵4X4_Array1D', name='矩阵')
		
		self.f_toCPP(self.id_data)
		
		
	def f_toCPP(self, tree):
		新创建 = engineLib.flexCAPI.f_创建取物体变换节点(ctypes.c_wchar_p(tree.name), ctypes.c_wchar_p(self.name), self.f_getPyObject(tree));
		if 新创建 :
			f_update_物体坐标系转换(self, None)
			self.inputs['物体'].f_update()
			self.outputs['移动'].f_update()
			self.outputs['旋转'].f_update()
			self.outputs['缩放'].f_update()
		#else:
		
			#self.outputs['矩阵'].f_update()


	def draw_buttons(self, context, layout):
		layout.prop(self, 'm_坐标系转换')
		#layout.prop(self, 'm_轴向')
	
	def f_update(self):
		物体 = self.inputs['物体'].f_getData()
		#print('取物体属性变换 ======物体====== ', 物体)
		if 物体 == None : return
		#mat = mathutils.Matrix()
		#旋转矩阵 = mat.Rotation(math.radians(90), 4, 'X')
		#缩放矩阵 = mat.Scale(-1, 4, (0,0,1))
		data = []
		for obj in 物体:
			#loc = (obj.location.x, -obj.location.z, -obj.location.y)
			#rot = (-obj.rotation_euler.x, obj.rotation_euler.z, -obj.rotation_euler.y)
			#sca = (obj.scale.x, obj.scale.z, obj.scale.y)
			#loc, rot, sca = obj.decompose()
			#data.append([loc, rot, sca])
			data.append([tuple(obj.location), tuple(obj.rotation_euler), tuple(obj.scale)])
		#print('取物体属性变换 ============ ', data)
		engineLib.flexCAPI.f_node_传入BL数据(ctypes.c_wchar_p(self.id_data.name), ctypes.c_wchar_p(self.name), ctypes.py_object(data));
		

class C_NODE_MENU_get物体变换属性(bpy.types.Operator):
	bl_idname = 'node.global_node_get_object_transform'
	bl_label = '取对象变换'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_get物体变换属性', use_transform=True)
		return {'FINISHED'}






class C_set物体变换属性(基类.C_Node_基类):
	bl_dname = 'bl_node_set物体属性变换'
	bl_label = '置物体属性变换'
	
	#m_变换方式 = bpy.props.EnumProperty(items=E_类型枚举_变换, default='TYPE_位置', name="变换方式", update=f_update_变换方式_物体属性set变换)
	m_坐标系转换 = bpy.props.EnumProperty(items=基类.E_类型枚举_坐标系轴向, default='TYPE_左手转右手', name="坐标系转换", update=f_update_物体坐标系转换)
	def init(self, context):
		super(C_set物体变换属性, self).f_init(context)
		self.inputs.new('C_Socket_物体_Array1D', name='物体')
		self.inputs.new('C_Socket_Vec3_Array1D', name='移动')
		self.inputs.new('C_Socket_Vec3_Array1D', name='旋转')
		self.inputs.new('C_Socket_Vec3_Array1D', name='缩放')
		
		self.inputs.new('C_Socket_矩阵4X4_Array1D', name='矩阵')

		self.f_toCPP(self.id_data)
		
		
	def f_toCPP(self, tree):
		是否更新 = engineLib.flexCAPI.f_创建置物体变换节点(ctypes.c_wchar_p(tree.name), ctypes.c_wchar_p(self.name), self.f_getPyObject(tree));
		if 是否更新 :
			self.inputs['物体'].f_update()
			self.inputs['移动'].f_update()
			self.inputs['旋转'].f_update()
			self.inputs['缩放'].f_update()
			self.inputs['矩阵'].f_update()
		
		if len(self.inputs) > 1 :
			for i in range(len(self.inputs)):
				self.inputs[i].f_update()
		
	def update(self):
		if self.inputs['矩阵'].is_linked:
			self.inputs['移动'].enabled = False
			self.inputs['旋转'].enabled = False
			self.inputs['缩放'].enabled = False
		else:
			self.inputs['移动'].enabled = True
			self.inputs['旋转'].enabled = True
			self.inputs['缩放'].enabled = True
		#print('*******************************C_set物体变换属性')
		super(C_set物体变换属性, self).update()
		
	def f_update(self):
		data = engineLib.flexCAPI.f_取节点数据(ctypes.c_wchar_p(self.id_data.name), ctypes.c_wchar_p(self.name));
		#print('data =============== ', data)
		if data == None : return
		
		if data[0] == "矩阵" :
			for 元素 in zip(data[1], data[2]):
				#print('元素=============', 元素[0], 元素[1])
				if 元素[0] : 元素[0].matrix_world = 元素[1]
				
		elif data[0] == "分量" :
			if data[2] :
				for 元素 in zip(data[1], data[2]):
					元素[0].location = 元素[1]
			if data[3] :
				for 元素 in zip(data[1], data[3]):
					元素[0].rotation_euler = 元素[1]
			if data[4] :
				for 元素 in zip(data[1], data[4]):
					元素[0].scale = 元素[1]
		


class C_NODE_MENU_set物体变换属性(bpy.types.Operator):
	bl_idname = 'node.global_node_set_object_transform'
	bl_label = '设置对象变换'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_set物体变换属性', use_transform=True)
		return {'FINISHED'}













def f_update_轴向_物体属性插帧变换(self, context):
	#输入轴数据插座
	if self.m_设置轴向 == 'TYPE_轴向单例' :
		self.inputs['X'].hide = True
		self.inputs['Y'].hide = True
		self.inputs['Z'].hide = True
		
		self.inputs['值'].hide = False
		self.inputs['通道'].hide = False
	
	elif self.m_设置轴向 == 'TYPE_X_Y_Z' :
		self.inputs['X'].hide = False
		self.inputs['Y'].hide = False
		self.inputs['Z'].hide = False

		self.inputs['值'].hide = True
		self.inputs['通道'].hide = True

	elif self.m_设置轴向 == 'TYPE_XYZ' :
		self.inputs['X'].hide = True
		self.inputs['Y'].hide = True
		self.inputs['Z'].hide = True

		self.inputs['通道'].hide = True

		self.inputs['值'].hide = False
		




































def f_update_插入帧_物体属性变换(self, context):
	if context :
		self.id_data.f_节点数据更新_更新树([self])


class C_对象_变换_插帧(基类.C_Node_基类):
	bl_dname = 'bl_node_对象_变换_插帧'
	bl_label = '对象变换插帧'
	
	m_data_path = bpy.props.EnumProperty(items=基类.E_变换类型枚举, name="路径", default='location', update=f_update_插入帧_物体属性变换)
	def init(self, context):
		super(C_对象_变换_插帧, self).f_init(context)
		self.inputs.new('C_Socket_物体_Array1D', name='物体')
		self.inputs.new('C_Socket_F32_Array1D', name='帧')
		self.inputs.new('C_Socket_Vec3_Array1D', name='值')
		
		self.f_toCPP(self.id_data)
		
	def f_toCPP(self, tree):
		新创建 = engineLib.flexCAPI.f_创建_物体变换插帧_节点(ctypes.c_wchar_p(tree.name), ctypes.c_wchar_p(self.name), self.f_getPyObject(tree));
		if 新创建 :
			self.inputs['帧'].f_update()
			self.inputs['值'].f_update()


	def draw_buttons(self, context, layout):
		layout.prop(self, 'm_data_path')
		
	def f_update(self):
		objs = self.inputs['物体'].f_getData()
		
		
		path = str(self.m_data_path)
		
		帧 = self.inputs['帧'].f_getData()
		值 = self.inputs['值'].f_getData()
		
		
		objNum = len(objs)
		
		if objNum <= 0 or len(帧) == 0 : return

		#print('path ======== ', objNum, len(值), len(帧))
		
		值是否独立 = len(值) >= objNum
		帧是否独立 = len(帧) >= objNum
		
		index = 0
		for obj in objs :
			if 帧是否独立 :
				帧值 = 帧[index]
			else:
				帧值 = 帧[0]

			if 值是否独立 :
				co = 值[index]
			else:
				co = 值[0]

			for i in range(3):
				#print('path = ', type(值), 值是否独立, index, i, obj.name, 帧值, 值)
				f = bl_对象变换帧.f_getObject曲线(obj, path, i)
				f.keyframe_points.insert(帧值, co[i])
				f.keyframe_points[-1].interpolation = 'BEZIER'

			index += 1


class C_NODE_MENU_对象_变换_插帧(bpy.types.Operator):
	bl_idname = 'node.global_node_object_trenform_keyframe_insert'
	bl_label = '对象变换插帧'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_对象_变换_插帧', use_transform=True)
		return {'FINISHED'}











		

def f_update_变换方式_物体属性清除变换帧(self, context):
	if context :
		self.id_data.f_节点数据更新_更新树([self])


class C_对象_清除_变换帧(基类.C_Node_基类):
	bl_dname = 'bl_node_对象_变换_清除帧'
	bl_label = '对象清除变换帧'
	
	m_data_path = bpy.props.EnumProperty(items=基类.E_变换类型枚举, name="路径", default='location', update=f_update_变换方式_物体属性清除变换帧)
	m_删除所有 = bpy.props.BoolProperty(default=True)
	def init(self, context):
		super(C_对象_清除_变换帧, self).f_init(context)
		self.inputs.new('C_Socket_物体_Array1D', name='物体')
		self.inputs.new('C_Socket_I32_Array1D', name='帧')

		self.f_toCPP(self.id_data)
		
	def update(self):
		if self.m_删除所有 :
			self.inputs['帧'].hide = True
		else:
			self.inputs['帧'].hide = False
		
	def draw_buttons(self, context, layout):
		layout.prop(self, 'm_data_path')
		layout.prop(self, 'm_删除所有')
		
	def f_toCPP(self, tree):
		是否更新 = engineLib.flexCAPI.f_创建_对象清除变换帧_节点(ctypes.c_wchar_p(tree.name), ctypes.c_wchar_p(self.name), self.f_getPyObject(tree));
		if 是否更新 :
			self.inputs['帧'].f_update()


	def f_update(self):
		objs = self.inputs['物体'].f_getData()
		#print('objs = ', objs)
		path = str(self.m_data_path)
		objNum = len(objs)
		
		帧 = self.inputs['帧'].f_getData()

		if self.m_删除所有 :
			for obj in objs :
				if obj.animation_data == None : continue
				
				bl_对象变换帧.f_删除指定路径曲线的所有关键点(obj, [path])

		else:
			for obj in objs :
				if obj.animation_data == None : continue
				
				for frameValue in 帧:
					bl_对象变换帧.f_删除指定关键帧(obj, frameValue, [path])
			


class C_NODE_MENU_对象_清除_变换帧(bpy.types.Operator):
	bl_idname = 'node.global_node_object_trenform_keyframe_clear'
	bl_label = '清除对象变换帧'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_对象_清除_变换帧', use_transform=True)
		return {'FINISHED'}





















classes = (
	C_get物体变换属性,
	C_NODE_MENU_get物体变换属性,

	C_set物体变换属性,
	C_NODE_MENU_set物体变换属性,



	C_对象_变换_插帧,
	C_NODE_MENU_对象_变换_插帧,

	C_对象_清除_变换帧,
	C_NODE_MENU_对象_清除_变换帧,


)

def register():
	for c in classes:
		bpy.utils.register_class(c)
		

def unregister():
	for c in classes:
		bpy.utils.unregister_class(c)

